{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "27fa33cf",
   "metadata": {},
   "outputs": [],
   "source": [
    "import openai\n",
    "from dotenv import load_dotenv\n",
    "import gradio as gr\n",
    "import os\n",
    "import json\n",
    "from datetime import datetime\n",
    "\n",
    "import httpx\n",
    "from fastapi import FastAPI\n",
    "import uvicorn\n",
    "import threading\n",
    "\n",
    "load_dotenv('.env',override=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e9407192",
   "metadata": {},
   "outputs": [],
   "source": [
    "app = FastAPI()\n",
    "\n",
    "@app.post('/mock/ticket')\n",
    "def booking(payload:dict):\n",
    "  dt = datetime.strptime(payload.get('date'), \"%Y/%m/%d\") \n",
    "  isoStr = dt.date().isoformat()\n",
    "  return {\"status\": \"success\", \"order_id\": f\"MOCK-FLIGHT-{isoStr}-001\"}\n",
    "\n",
    "# start server\n",
    "def run():\n",
    "    uvicorn.run(app, host=\"127.0.0.1\", port=8000)\n",
    "\n",
    "thread = threading.Thread(target=run, daemon=True)\n",
    "thread.start()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2229b6db",
   "metadata": {},
   "outputs": [],
   "source": [
    "openai_api_key = os.getenv('OPENAI_API_KEY')\n",
    "llm = openai.OpenAI(api_key=openai_api_key)\n",
    "\n",
    "system_message = \"You are a helpful assistant for an Airline called FlightAI. \"\n",
    "system_message += \"Give short, courteous answers, no more than 1 sentence. \"\n",
    "system_message += \"Always be accurate. If you don't know the answer, say so.\"\n",
    "\n",
    "async def booking_flight(departure, destination, date):\n",
    "  print(f\"Book the Flight Automatically, {departure} to {destination} at {date}.\")\n",
    "  reqBody = {\n",
    "    \"departure\": departure,\n",
    "    \"destination\": destination,\n",
    "    \"date\": date\n",
    "  }\n",
    "  async with httpx.AsyncClient() as client:\n",
    "    res = await client.post('http://127.0.0.1:8000/mock/ticket', json=reqBody)\n",
    "    print(res.text)\n",
    "    return res.text\n",
    "  \n",
    "book_function = {\n",
    "    \"name\": \"booking_flight\",\n",
    "    \"description\": \"async function for booking the flight ticket for customers and it will return the status and id of flight. Call this function whenever you were asked to book the flight, and you will automatically tell the status of the order and the book number! if customers don't provide their departure or destination or date you should inquire them courteous. Note that the date format you should keep them with %Y/%m/%d. for example when a customer asks 'Please help me book the ticket from <departure> to <destination>'\",\n",
    "    \"parameters\": {\n",
    "        \"type\": \"object\",\n",
    "        \"properties\": {\n",
    "            \"departure\": {\n",
    "                \"type\": \"string\",\n",
    "                \"description\": \"The city where the customer departure\",\n",
    "            },\n",
    "            \"destination\": {\n",
    "                \"type\": \"string\",\n",
    "                \"description\": \"The city that the customer wants to travel to\",\n",
    "            },\n",
    "            \"date\": {\n",
    "                \"type\": \"string\",\n",
    "                \"description\": \"The date of the flight \",\n",
    "            },\n",
    "        },\n",
    "        \"required\": [\"destination\", \"departure\", \"date\"],\n",
    "        \"additionalProperties\": False\n",
    "    }\n",
    "}\n",
    "\n",
    "async def handle_tool_call(message):\n",
    "    tool_call = message.tool_calls[0]\n",
    "    arguments = json.loads(tool_call.function.arguments)\n",
    "    departure = arguments.get('departure')\n",
    "    destination = arguments.get('destination')\n",
    "    date = arguments.get('date')\n",
    "    res = await booking_flight(departure, destination, date)\n",
    "    response = {\n",
    "        \"role\": \"tool\",\n",
    "        \"content\": json.dumps(res),\n",
    "        \"tool_call_id\": tool_call.id\n",
    "    }\n",
    "    return response\n",
    "\n",
    "tools = [{\"type\": \"function\", \"function\": book_function}]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5bf9656f",
   "metadata": {},
   "outputs": [],
   "source": [
    "res = await booking_flight('Taiwan', \"NewYork\", \"2025/12/03\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d2924055",
   "metadata": {},
   "outputs": [],
   "source": [
    "async def chat(message, history):\n",
    "  messages = [{\"role\": \"system\", \"content\": system_message}] + history + [{\"role\": \"user\", \"content\": message}]\n",
    "  res = llm.chat.completions.create(messages=messages,\n",
    "                                    model=\"gpt-4.1-mini\",\n",
    "                                    tools=tools)\n",
    "  \n",
    "  if res.choices[0].finish_reason == 'tool_calls':\n",
    "    message = res.choices[0].message\n",
    "    toolResponse = await handle_tool_call(message)\n",
    "    messages.append(message)\n",
    "    messages.append(toolResponse)\n",
    "    res = llm.chat.completions.create(messages=messages,\n",
    "                                    model=\"gpt-4.1-mini\")\n",
    "\n",
    "  return res.choices[0].message.content\n",
    "\n",
    "gr.ChatInterface(fn=chat,type=\"messages\").launch()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "3.10.15",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
